package com.facedemo.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import com.facedemo.MyApplication;
import com.facedemo.R;
import com.facedemo.bean.FaceTraceInfo;
import com.facedemo.bean.LiveStatus;
import com.facedemo.utils.LogUtils;

import java.io.UnsupportedEncodingException;
import java.util.List;

public class FaceMarkSurface extends SurfaceView implements SurfaceHolder.Callback {
    protected SurfaceHolder surfaceHolder;
    protected Context context;
    private int width, height;

    private Paint faceRectLinePaint;//人脸框画笔
    private TextPaint textPaint;//人名画笔
    private float textAvail = 0;

    public FaceMarkSurface(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        getHolder().addCallback(this);
        setZOrderOnTop(true);
        setZOrderMediaOverlay(true);
        getHolder().setFormat(PixelFormat.TRANSPARENT);

        faceRectLinePaint = new Paint();
        faceRectLinePaint.setAntiAlias(true);
        faceRectLinePaint.setStrokeWidth((float) 4);
        faceRectLinePaint.setStyle(Paint.Style.STROKE);
        faceRectLinePaint.setColor(Color.RED);

        textPaint = new TextPaint();
        textPaint.setColor(context.getResources().getColor(R.color.white));
        textPaint.setStyle(Paint.Style.FILL);
        textPaint.setAntiAlias(true);
        textPaint.setFakeBoldText(true);
        textPaint.setShadowLayer(2, 4, 4, context.getResources().getColor(R.color.txt_shoadow));
        textPaint.setTextSize(26);
        textAvail = textPaint.measureText("Harry James Potter");
    }

    public void surfaceCreated(SurfaceHolder holder) {
        surfaceHolder = holder;
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        this.width = width;
        this.height = height;
        LogUtils.printI("FaceMarkSurface-->surfaceChanged h:"+height+" w:"+width);
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        surfaceHolder = null;
    }

    public boolean hasDrawInfo = false;

    public void clearDrawInfo() {
        if (surfaceHolder != null && hasDrawInfo) {
            hasDrawInfo = false;
            SurfaceHolder holder = surfaceHolder;
            try {
                Canvas canvas = holder.lockCanvas();
                if (canvas != null) {
                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
                    holder.unlockCanvasAndPost(canvas);
                }
            } catch (Exception e) {
                e.printStackTrace();
                if (null != null) {
                    holder.unlockCanvasAndPost(null);
                }
            } catch (Throwable th) {
                if (null != null) {
                    holder.unlockCanvasAndPost(null);
                }
            }
        }
    }

    public void drawInfo(Rect rect, int w, int h) {
        if(surfaceHolder==null) return;
        if(rect==null) return;

        hasDrawInfo = true;
        SurfaceHolder holder = surfaceHolder;
        Canvas canvas = null;
        try {
            canvas = holder.lockCanvas();
            if (canvas != null) {
                canvas.drawColor(0, PorterDuff.Mode.CLEAR);
                Rect rectSurface = getFitRect(rect,w,h);
                drawRect(canvas,rectSurface);
                holder.unlockCanvasAndPost(canvas);
            }
        } catch (Exception e) {
            e.printStackTrace();
            if (canvas != null) {
                holder.unlockCanvasAndPost(canvas);
            }
        } catch (Throwable th) {
            if (canvas != null) {
                holder.unlockCanvasAndPost(canvas);
            }
        }
    }

    public void drawInfo(List<FaceTraceInfo> faceTraceInfos, boolean isShowName) {
        if(surfaceHolder==null) return;
        if(faceTraceInfos==null || faceTraceInfos.size()==0) return;

        hasDrawInfo = true;
        SurfaceHolder holder = surfaceHolder;
        Canvas canvas = null;
        try {
            canvas = holder.lockCanvas();
            if (canvas != null) {
                canvas.drawColor(0, PorterDuff.Mode.CLEAR);
                for(FaceTraceInfo info:faceTraceInfos) {
                    if(info.liveStatus == LiveStatus.NO){
                        faceRectLinePaint.setColor(Color.GRAY);//非活体 显示灰色框
                    } else if(info.getRecognizeStatus()==2 || !isShowName) {
                        faceRectLinePaint.setColor(Color.GREEN);
                    } else {
                        faceRectLinePaint.setColor(Color.RED);
                    }
                    Rect rectSurface = getFitRect(info.getRect(),info.getBitmapW(),info.getBitmapH());
                    drawRect(canvas,rectSurface);
                    if(isShowName && info.getRecognizeStatus()==2) {
                        drawName(canvas,rectSurface,info.getResultName());
                    }
                }
                holder.unlockCanvasAndPost(canvas);
            }
        } catch (Exception e) {
            e.printStackTrace();
            if (canvas != null) {
                holder.unlockCanvasAndPost(canvas);
            }
        } catch (Throwable th) {
            if (canvas != null) {
                holder.unlockCanvasAndPost(canvas);
            }
        }
    }

    private void drawRect(Canvas canvas, Rect rectSurface) {
        if(canvas==null) return;
        if(rectSurface==null) return;
        int lineLength = (rectSurface.right - rectSurface.left) / 4;
        //画人脸框
        canvas.drawLine(rectSurface.left,rectSurface.top,rectSurface.left+lineLength,rectSurface.top,faceRectLinePaint);
        canvas.drawLine(rectSurface.left,rectSurface.top,rectSurface.left,rectSurface.top+lineLength,faceRectLinePaint);

        canvas.drawLine(rectSurface.right-lineLength,rectSurface.top,rectSurface.right,rectSurface.top,faceRectLinePaint);
        canvas.drawLine(rectSurface.right,rectSurface.top,rectSurface.right,rectSurface.top+lineLength,faceRectLinePaint);

        canvas.drawLine(rectSurface.left,rectSurface.bottom-lineLength,rectSurface.left,rectSurface.bottom,faceRectLinePaint);
        canvas.drawLine(rectSurface.left,rectSurface.bottom,rectSurface.left+lineLength,rectSurface.bottom,faceRectLinePaint);

        canvas.drawLine(rectSurface.right,rectSurface.bottom-lineLength,rectSurface.right,rectSurface.bottom,faceRectLinePaint);
        canvas.drawLine(rectSurface.right-lineLength,rectSurface.bottom,rectSurface.right,rectSurface.bottom,faceRectLinePaint);
    }

    private void drawName(Canvas canvas,Rect rectSurface,String name) {
        if(canvas==null) return;
        if(rectSurface==null) return;
        if(name==null) return;
        float nameLength = 0;
        try {
            nameLength = name.getBytes("utf-8").length;
        } catch (UnsupportedEncodingException e) {
            nameLength = name.length();
        }
        if(nameLength>=18) {
            textPaint.setTextSize(24);
            name = (String) TextUtils.ellipsize(name, textPaint, textAvail, TextUtils.TruncateAt.END);
        } else if(nameLength>=12) {
            textPaint.setTextSize(26);
        } else {
            textPaint.setTextSize(30);
        }
        canvas.drawText(name, rectSurface.centerX() - (textPaint.measureText(name) / 2.0f), rectSurface.top+3, textPaint);
    }

    /**
     * 把人脸检测的Rect，根据Surface的实际大小进行调整
     * @param rect 人脸检测的Rect
     * @param dataWidth 图像的实际宽度
     * @param dataHeight 图像的实际高度
     * @return 调整后的新Rect
     * */
    private Rect getFitRect(Rect rect, int dataWidth, int dataHeight) {
        if(rect==null) return null;
        Rect result = new Rect();
//        int width_5 = (rect.right - rect.left) / 6;//把人脸框 宽度增大1/6
        result.left = (rect.left * width / dataWidth);
        result.right = (rect.right * width / dataWidth);
        //如果摄像头实际回调画面非镜像，而预览画面镜像，则左右翻转人脸框
        if(!MyApplication.dCamera.isMirroring) {
            int left = result.left;
            result.left = width - result.right;
            result.right = width - left;
        }
        result.top = rect.top * height / dataHeight;
        result.bottom = rect.bottom * height / dataHeight;
        return result;
    }
}
